Skip to content

Latest commit

Β 

History

History
278 lines (219 loc) Β· 6.4 KB

File metadata and controls

278 lines (219 loc) Β· 6.4 KB

큐

QueueλŠ” FIFO 원리에 λ”°λ₯Έ μ •λ ¬λœ μ»¬λ ‰μ…˜μ΄λ‹€.

큐 λ§Œλ“€κΈ°

function Queue() {
  let items = [];

  this.enqueue = function (element) {
    // O(1)
    items.push(element);
  };

  this.dequeue = function () {
    // O(n)
    return items.shift();
  };

  this.front = function () {
    // O(1)
    return items[0];
  };

  this.isEmpty = function () {
    return !items.length;
  };

  this.clear = function () {
    items = [];
  };

  this.size = function () {
    return items.length;
  };

  this.print = function () {
    console.log(items.toString());
  };
}

Arrayλ₯Ό μ‚¬μš©ν•΄ κ΅¬ν˜„ν•˜λ©΄ μƒκΈ°λŠ” 단점은 dequeue μ—μ„œ 맀번 O(n) 번의 연산이 λ°œμƒν•œλ‹€λŠ” 것이닀. queue의 μ‚¬μ΄μ¦ˆκ°€ 클 경우 μ˜€λ²„ν—€λ“œκ°€ 많이 λ°œμƒν•  κ°€λŠ₯성이 크기 λ•Œλ¬Έμ— λ‹€μŒκ³Ό 같이 κ΅¬ν˜„ν•˜μž.

function Queue() {
  function Node(value) {
    this.value = value;
    this.next = null;
  }

  let front = null;
  let rear = null;
  let length = 0;

  this.enqueue = function (value) {
    // μƒˆλ‘œμš΄ λ…Έλ“œ 생성
    const newNode = new Node(value);

    if (!rear) {
      // 처음 enqueueν•˜λŠ” 경우
      front = rear = newNode;
    } else {
      // κ°€μž₯ 끝 λ…Έλ“œμ— μƒˆλ‘œμš΄ λ…Έλ“œ μΆ”κ°€
      rear.next = newNode;
      // 끝 포인터 λ³€κ²½
      rear = newNode;
    }
    length += 1;
  };

  this.dequeue = function () {
    if (!front) return null;

    // κ°€μž₯ 첫 번째 λ…Έλ“œ κ°€μ Έμ˜΄
    const dequeuedNode = front;
    // 두 번째 λ…Έλ“œλ₯Ό μ‹œμž‘ ν¬μΈν„°λ‘œ μ„€μ •
    front = front.next;
    if (!front) {
      // λ§ˆμ§€λ§‰ λ…Έλ“œμ˜€μ„ 경우
      rear = null;
    }
    length -= 1;
    return dequeuedNode.value;
  };

  this.front = function () {
    return front;
  };

  // ...μ΄ν•˜ μƒλž΅
}

μœ„μ™€ 같이 Linked List둜 κ΅¬ν˜„ν•˜κ²Œ 되면 enqueue, dequeue λͺ¨λ‘ O(1) λ§Œμ— μš”μ†Œλ₯Ό μΆ”κ°€, μ œκ±°κ°€ κ°€λŠ₯ν•˜λ‹€.

μš°μ„ μˆœμœ„ 큐

μš°μ„ μˆœμœ„ νλŠ” 각 μš”μ†Œμ— μš°μ„ μˆœμœ„λ₯Ό λΆ€μ—¬ν•΄ μ˜€λ¦„μ°¨μˆœ, λ‚΄λ¦Όμ°¨μˆœμœΌλ‘œ μ •λ ¬λœ μ»¬λ ‰μ…˜μœΌλ‘œ μ‚¬μš©ν•˜λŠ” μžλ£Œκ΅¬μ‘°μ΄λ‹€.

function PriorityQueue() {

	function QueueElement(element, priority) {
		this.element = element;
		this.priority = priority;
	}

	let items = [];

	this.enqueue = function(element, priority) {
		const element = new QueueElement(element, priority);

		if (this.isEmpty()) {
			items.push(element);
		} else {
			const added = false;
			for (let i = 0; i < items.length; i++) {
				if (element.priority < items[i].priority) {
					items.splice(i, 0, element);
					added = true;
					break;
				}
			}
			if (!added) {
				items.push(element);
			}

			// o(N log N)
			// items.sort();
	}

	// ...μ΄ν•˜ μƒλž΅
}

μœ„ μ½”λ“œλŠ” O(n) 의 μ‹œκ°„μ΄ κ±Έλ¦¬λ―€λ‘œ, λŠλ¦¬λ‹€κ³  ν•  수 μžˆλ‹€.

class MinHeap {
  constructor() {
    this.heap = [null];
  }

  push(value) {
    this.heap.push(value);
    let currentIndex = this.heap.length - 1;
    let parentIndex = Math.floor(currentIndex / 2);

    while (parentIndex !== 0 && this.heap[parentIndex] > value) {
      const temp = this.heap[parentIndex];
      this.heap[parentIndex] = value;
      this.heap[currentIndex] = temp;

      currentIndex = parentIndex;
      parentIndex = Math.floor(currentIndex / 2);
    }
  }

  pop() {
    if (this.heap.length === 2) return this.heap.pop(); // 루트 μ •μ λ§Œ 남은 경우

    const returnValue = this.heap[1];
    this.heap[1] = this.heap.pop();

    let currentIndex = 1;
    let leftIndex = 2;
    let rightIndex = 3;
    while (
      this.heap[currentIndex] > this.heap[leftIndex] ||
      this.heap[currentIndex] > this.heap[rightIndex]
    ) {
      if (this.heap[leftIndex] > this.heap[rightIndex]) {
        const temp = this.heap[currentIndex];
        this.heap[currentIndex] = this.heap[rightIndex];
        this.heap[rightIndex] = temp;
        currentIndex = rightIndex;
      } else {
        const temp = this.heap[currentIndex];
        this.heap[currentIndex] = this.heap[leftIndex];
        this.heap[leftIndex] = temp;
        currentIndex = leftIndex;
      }
      leftIndex = currentIndex * 2;
      rightIndex = currentIndex * 2 + 1;
    }

    return returnValue;
  }
}

heap은 μ‚½μž…κ³Ό μ‚­μ œ λͺ¨λ‘ O(log n) 의 μ‹œκ°„μ΄ μ†Œμš”λ˜λ―€λ‘œ 정렬을 μ‚¬μš©ν•˜λŠ” 것보닀 λΉ λ₯Έ 속도λ₯Ό λ‚Ό 수 μžˆλ‹€.

이렇듯 μš°μ„ μˆœμœ„ νλŠ” 정렬에 따라 μ΅œμ†Œ μš°μ„ μˆœμœ„ 큐 λ˜λŠ” μ΅œλŒ€ μš°μ„ μˆœμœ„ 큐둜 λΆˆλ¦°λ‹€.

ν™˜ν˜• 큐

또 λ‹€λ₯Έ 큐의 λ³€ν˜•μΈ ν™˜ν˜• 큐λ₯Ό μ•Œμ•„λ³΄μž.

뜨거운 감자 κ²Œμž„(μ‘°μ„Έν‘ΈμŠ€ 문제)

원을 그리고 μ„  아이듀이 뜨거운 감자λ₯Ό μ˜† μ‚¬λžŒμ—κ²Œ μ΅œλŒ€ν•œ 빨리 μ „λ‹¬ν•˜λ‹€κ°€, κ°‘μžκΈ° λͺ¨λ‘ λ™μž‘μ„ λ©ˆμΆ”κ³  κ·Έ λ•Œ 뜨거운 감자λ₯Ό 손에 λ“€κ³  μžˆλŠ” 아이λ₯Ό λ²ŒμΉ™μœΌλ‘œ 퇴μž₯μ‹œν‚€λŠ” κ²Œμž„μ΄λ‹€.

// ...Queue

// N -> nameList.length
// K -> num
// O(NK)
function hotPotato(nameList, num) {
  // linked list
  const queue = new Queue();

  for (let i = 0; i < nameList.length; i++) {
    queue.enqueue(nameList[i]);
  }

  let eliminated = "";
  while (queue.size() > 1) {
    for (let i = 0; i < num; i++) {
      queue.enqueue(queue.dequeue());
    }
    eliminated = queue.dequeue();
    console.log(eliminated + " (을)λ₯Ό 뜨거운 감자 κ²Œμž„μ—μ„œ 퇴μž₯μ‹œν‚΅λ‹ˆλ‹€.");
  }
  // O(N * K)

  return queue.dequeue();
}

let players = ["Alice", "Bob", "Charlie", "David", "Eve"];
let numPasses = 7;
console.log("winner:", hotPotato(players, numPasses));

μ—¬λ‹΄μœΌλ‘œ μ•Œκ³ λ¦¬μ¦˜μ„ ν™œμš©ν•˜λ©΄ 자료ꡬ쑰 없이 더 λΉ λ₯Έ μ‹œκ°„(O(n)) μ•ˆμ— ν•΄κ²° κ°€λŠ₯ν•˜λ‹€

점화식(μž¬κ·€)

// 점화식: f(n, k) = ((f(n - 1, k) + k) % n) + 1
// f(1, k) = 1 : 기저쑰건
// f(n - 1, k) -> n - 1 : λ‹€μŒ μš”μ†Œ μœ„μΉ˜
// k:  λ‹€μŒ μš”μ†Œλ‘œ 이동해야할 횟수
// (f(n - 1, k) + k) % n :
//     ex) 5 > 7
//     7 % 5 = 2
//     2 + 1 = 3

// O(N)
function findTheWinner(n, k) {
  if (n === 1) return 1;
  return ((findTheWinner(n - 1, k) + k) % n) + 1;
}
let players = ["Alice", "Bob", "Charlie", "David", "Eve"];
let numPasses = 7;

console.log("winner:", players[findTheWinner(players.length, numPasses) - 1]);

λ™μ κ³„νšλ²•(DP)

function findTheWinner(n, k) {
  let s = 1;

  for (let i = 1; i < n + 1; i++) {
    s = ((s + k) % i) + 1;
  }
  return s;
}
let players = ["Alice", "Bob", "Charlie", "David", "Eve"];
let numPasses = 7;

console.log("winner:", players[findTheWinner(players.length, numPasses) - 1]);